from django.contrib.auth.models import AnonymousUser
from django_redis import get_redis_connection
from rest_framework.permissions import BasePermission, OR
from rest_framework import HTTP_HEADER_ENCODING

from mysqldb.models import *
import logging

logger = logging.getLogger("sys_oplog")


def has_placer(request):
    header = request.META.get("HTTP_PLACE_ID")
    if isinstance(header, str):
        header = header.encode(HTTP_HEADER_ENCODING)
    return header


class AllPermissions(BasePermission):
    """允许所有权限"""

    def has_permission(self, request, view):
        return True

    def has_object_permission(self, request, view, obj):
        return True


class MyPermissions(BasePermission):
    """自定义后台权限"""

    message = "后台用户权限不够"

    def has_name(self, view):
        """返回类名"""
        n = repr(view).split(" ")[0].split(".")[-1]
        return n

    def verify_objects_permission(self, request, obj_id):
        """验证对象权限"""
        try:
            AllinpayUserobjectList.objects.get(uid=request.user.id, pid=obj_id)
        except BaseException as err:
            return False
        else:
            return True

    def verify_backends_permission(self, gid, view, act):
        """验证视图权限"""
        try:
            permID = AllinpayAuthViews.objects.get(name=view, act=act.upper())
            x = AllinpayAuthGroupPermissions.objects.get(
                group_id=gid, permission_id=permID.id
            )
        except BaseException as err:
            return False
        else:
            return True

    def do_write_log(self, uid, act, view, obj=None):
        """写入操作日志"""
        if hasattr(view, "__info__"):
            ainfo = view.__info__.get(act)
        else:
            ainfo = view.__title__
        logger.info(f"[{uid}] [{act}] [{self.has_name(view)}] [{ainfo}] {obj}")

    def has_permission(self, request, view):
        """视图级访问权限"""
        print("管理员验证视图", request.method)
        # 验证登录
        if not request.user:
            return False  # 禁止未登录访问
        # 验证类型
        if not isinstance(request.user, AllinpayUserList):
            return False
        if request.user.is_super:
            # self.do_write_log(request.user.id, request.method, view)
            return True  # 天使模式
        # 后台超级管理员
        if request.user.group == 2:
            # self.do_write_log(request.user.id, request.method, view)
            return True
        # 禁止编辑超级用户
        if view.__title__ == "用户超级":
            return False

        # 格式化类名
        info = self.has_name(view)
        # 验证视图权限
        isContinue = self.verify_backends_permission(
            request.user.group, info, request.method
        )
        if isContinue and request.method == "POST":
            self.do_write_log(request.user.id, request.method, view)
        return isContinue

        # 默认动作
        # return True

    def has_object_permission(self, request, view, obj):
        """对象级访问权限"""
        print("管理员验证对象", request.method)
        if not request.user:
            return False  # 禁止未登录访问

        if not isinstance(request.user, AllinpayUserList):
            return False  # 验证类型

        if request.user.is_super:
            # self.do_write_log(request.user.id, request.method, view)
            return True  # 天使模式

        # 后台超级管理员
        if request.user.group == 2:
            # self.do_write_log(request.user.id, request.method, view)
            return True

        # 对象级过滤
        # if isinstance(obj, AllinpayAuthGroup):
        #     self.do_write_log(request.user.id, request.method, view)
        #     return True  # 后台角色表包含pid字段

        # 对象级过滤
        if hasattr(obj, "pid") and not isinstance(obj, AllinpayAuthGroup):
            pid = getattr(obj, "pid")
            isContinue = self.verify_objects_permission(request, pid)
            if not isContinue:
                return False

        self.do_write_log(request.user.id, request.method, view, obj.id)
        # 默认动作
        return True


class BoxPermissions(BasePermission):
    """自定义场所盒子权限"""

    message = "后台盒子权限不够"

    def get_placer(self, request):
        header = request.META.get("HTTP_PLACE_ID")
        if isinstance(header, str):
            header = header.encode(HTTP_HEADER_ENCODING)
        return header

    def has_permission(self, request, view):
        # 验证登录
        if not request.user:
            return False  # 禁止未登录访问
        if not isinstance(request.user, AllinpayPlaceList):
            return False  # 验证类型
        # 默认动作
        return True

    def has_object_permission(self, request, view, obj):
        """对象级访问权限"""
        if not request.user:
            return False  # 禁止未登录访问
        if not isinstance(request.user, AllinpayPlaceList):
            return False  # 验证类型
        # 默认动作
        return True


class WeChatPermissions(BasePermission):
    """允许所有权限"""

    message = "微信端员工权限不够"
    exception_views = [
        "UpdateImagesViews",  # 上传图片
        "WeChatBindPlaceViewSet",  # 微信绑定场所请求
        "WeChatAllinpayPlacestaffListViewSet",  # 微信绑定场所列表
        "WeChatAllinpayPlaceListViewSet",  # 微信场所列表
        "WeChatStaffListViewSet",  # 微信员工信息
        "WeChatStaffBindViewSet",  # 微信手机绑定
        "WeChatLoginPhoneViewSet",  # 微信手机登录
        "WeChatLoginViewSet",  # 微信登录
        "WeChatChangePlaceViewSet",  # 微信登录场所
        "AllinpayStaffListViewSet",  # 用户信息
    ]

    def has_name(self, view):
        """返回类名"""
        n = repr(view).split(" ")[0].split(".")[-1]
        return n

    def has_place(self, sid):
        """返回登录场所对象"""
        try:
            pid = get_redis_connection("loginPlace").get(sid)
            place = AllinpayPlaceList.objects.get(id=pid)
        except BaseException as err:
            return None
        else:
            return place

    def has_staff(self, sid):
        """返回登录员工对象"""
        try:
            staff = AllinpayStaffList.objects.get(id=sid)
        except BaseException as err:
            return None
        else:
            return staff

    def verify_view(self, view, method, sid, pid):
        """场所端验证权限"""
        print("场所端验证权限", method)
        try:
            vid = AllinpayAuthViews.objects.get(name=view, act=method.upper())
        except BaseException as err:
            return True
        try:
            role = AllinpayPlacestaffRole.objects.filter(pid=pid, sid=sid).values_list(
                "rid", flat=True
            )
            perm = AllinpayPlacerolePermYun.objects.filter(
                rid__in=list(role), vid=vid.id
            ).values_list("id", flat=True)
            return True if len(list(perm)) else False
        except BaseException as err:
            return False

    def has_permission(self, request, view):
        """视图权限"""
        print("微信验证视图", request.method)
        # 验证登录
        if not request.user:
            return False  # 禁止未登录访问
        # 验证类型
        if not isinstance(request.user, AllinpayStaffList):
            return False
        # 不验证视图关键参数
        if self.has_name(view) in self.exception_views:
            return True
        # 验证登录门店
        Place, Staff = self.has_place(request.user.id), self.has_staff(request.user.id)
        if not Place or not Staff:
            return False
        # 验证权限  # 格式化视图名称名 # 验证用户权限
        viewName = self.has_name(view)
        isAccept = self.verify_view(viewName, request.method, Staff.id, Place.id)
        print(request.method, viewName, isAccept)
        return isAccept
        # return True

    def has_object_permission(self, request, view, obj):
        """对象权限"""
        print("微信验证对象", request.method)
        print(0, request.method, view)
        # 验证登录
        if not request.user:
            return False  # 禁止未登录访问
        # 验证类型
        if not isinstance(request.user, AllinpayStaffList):
            return False
        # 不验证视图关键参数
        if self.has_name(view) in self.exception_views:
            return True

        print(1, request.method, view)

        # 允许查询个人信息-自己
        if isinstance(obj, AllinpayStaffList) and request.method == "GET":
            if request.user.id == obj.id:
                return True

        # 修改个人信息
        if isinstance(obj, AllinpayStaffList) and request.method == "PUT":
            if request.user.phone == Place.telephone:
                return True
            if request.user.id == obj.id:
                return True
            if not request.user.id == obj.id:
                return False

        # 验证登录门店
        Place, Staff = self.has_place(request.user.id), self.has_staff(request.user.id)
        if not Place or not Staff:
            return False

        print(2, request.method, view)

        # 禁止审核员工离职-自己
        if isinstance(obj, AllinpayPlacestaffList) and request.method == "PUT":
            if request.user.id == obj.sid:
                return False

        # 禁止编辑角色-管理员
        if isinstance(obj, AllinpayPlaceroleList) and obj.name == "管理员":
            return False

        # 禁止删除角色权限-管理员
        if isinstance(obj, AllinpayPlacerolePerm) and request.method == "DELETE":
            try:
                name = AllinpayPlaceroleList.objects.get(id=obj.rid).name
            except BaseException as err:
                return False
            else:
                if name == "管理员":
                    return False

        print(3, request.method, view)

        # 验证场所ID
        if hasattr(obj, "pid"):
            if Place.id != obj.pid:
                return False
            if isinstance(obj, AllinpayPlaceList) and Place.id != obj.id:
                return False

        print(4, request.method, view)

        return True


# =============================================


class BarPermissions(WeChatPermissions):
    message = "场所端员工权限不够"


# =============================================
class XboxPermissions(BasePermission):
    """自定义后台权限"""

    message = "三方端权限不够"

    def has_name(self, view):
        """返回类名"""
        n = repr(view).split(" ")[0].split(".")[-1]
        return n

    def has_permission(self, request, view):
        """视图级访问权限"""
        print("三方端验证视图", request.method)
        # 验证登录
        if not request.user:
            return False  # 禁止未登录访问
        # 验证类型
        if not isinstance(request.user, GamePlacetokenList):
            return False

        # 验证视图
        if self.has_name(view) == "GamePlaceconfLolBaseViewSet":
            return True if request.method == "GET" else False
        if self.has_name(view) == "GamePlaceconfLolLevelViewSet":
            return True if request.method == "GET" else False
        if self.has_name(view) == "GamePlaceconfLolTypesViewSet":
            return True if request.method == "GET" else False

        return True

    def has_object_permission(self, request, view, obj):
        """对象权限"""
        print("三方端验证对象", request.method)
        # 验证登录
        if not request.user:
            return False  # 禁止未登录访问
        # 验证类型
        if not isinstance(request.user, GamePlacetokenList):
            return False

        return True


class RboxPermissions(BasePermission):
    """自定义后台权限"""

    message = "三方端权限不够"

    def has_name(self, view):
        """返回类名"""
        n = repr(view).split(" ")[0].split(".")[-1]
        return n

    def has_permission(self, request, view):
        """视图级访问权限"""
        print("三方端验证视图", request.method)
        # 验证登录
        if not request.user:
            return False  # 禁止未登录访问
        # 验证类型
        if not isinstance(request.user, GamoPlacetokenList):
            return False

        # 验证视图
        # if self.has_name(view) == "GamePlaceconfLolBaseViewSet":
        #     return True if request.method == "GET" else False
        # if self.has_name(view) == "GamePlaceconfLolLevelViewSet":
        #     return True if request.method == "GET" else False
        # if self.has_name(view) == "GamePlaceconfLolTypesViewSet":
        #     return True if request.method == "GET" else False

        return True

    def has_object_permission(self, request, view, obj):
        """对象权限"""
        print("三方端验证对象", request.method)
        # 验证登录
        if not request.user:
            return False  # 禁止未登录访问
        # 验证类型
        if not isinstance(request.user, GamoPlacetokenList):
            return False

        return True
